﻿using System;
using System.Runtime.Caching;
using VerifyArgs;
using System.Collections.Generic;

namespace EP.Caching.Providers {
	public class ObjectCacheProvider : ICacheProvider {
		#region Fields / Properties
		private ObjectCache _Cache;
		#endregion

		#region Constructor
		public ObjectCacheProvider() {
			_Cache = MemoryCache.Default;

			Verify.NotNull(new { _Cache });
		}
		#endregion

		#region ICacheProvider Members
		public TimeSpan? SlidingTimeout { get; set; }

		public bool SupportsAbsoluteTimeout { get { return true; } }
		public DateTimeOffset? AbsoluteTimeout { get; set; }

		private IList<ChangeMonitor> _Monitors;
		public bool SupportsChangeMonitors { get { return true; } }
		public IList<ChangeMonitor> Monitors {
			get { return _Monitors ?? (_Monitors = new List<ChangeMonitor>()); }
		}

		public void Add<T>(string key, T value) {
			Verify.Args(new { key }).NotNullOrEmpty();

			var policy = new CacheItemPolicy();
			if (SlidingTimeout != null && SlidingTimeout.HasValue) {
				policy.SlidingExpiration = SlidingTimeout.Value;
			}

			if (AbsoluteTimeout != null && AbsoluteTimeout.HasValue) {
				policy.AbsoluteExpiration = AbsoluteTimeout.Value;
			}

			if (Monitors != null) {
				foreach (var item in Monitors) {
					policy.ChangeMonitors.Add(item);
				}
			}

			_Cache.Add(key, value, policy);
		}

		public bool Contains(string key) {
			Verify.Args(new { key }).NotNullOrEmpty();

			return _Cache.Contains(key);
		}

		public object Get(string key) {
			Verify.Args(new { key }).NotNullOrEmpty();

			return _Cache.Get(key);
		}
		public T Get<T>(string key) where T : class, IConvertible {
			Verify.Args(new { key }).NotNullOrEmpty();

			if (typeof(T) is IConvertible)
				return (T)Convert.ChangeType(_Cache.Get(key), typeof(T));

			return _Cache.Get(key) as T;
		}

		public void Remove(string key) {
			Verify.Args(new { key }).NotNullOrEmpty();

			if (_Cache.Contains(key))
				_Cache.Remove(key);
		}
		#endregion
	}
}
